Objectif de la formation : apprendre ou revoir…

  • Les possibilités de R
  • La création d’un projet
  • L’importation d’une base
  • Le recodage de données de types différents
  • La réalisation de tris croisés simples
  • La réalisation de graphiques simples

1. Présentation de R, RStudio et de l’environnement de travail

1.1 Rappel : Travailler sur une base de données (BDD)

Grâce aux logiciels dits “clic-boutons” : Excel, SPSS, Sphinx, etc.

  • Pas d’écriture de code
  • Facilité d’accès et d’utilisation (apprentissage rapide)

Mais

  • Aucun historique des changements et actions, ce qui rend difficile :
    1. le travail en collectif
    2. la reproductibilité des recherches
  • Si les données sont trop volumineuses, le logiciel risque d’être fortement ralenti

Ou via des langages de programmation : R, SAS, Python, C, C++, etc. On écrit une ligne de commande (des lignes de “code”), souvent exécutée dans un environnement de développement intégré (en anglais IDE).

  • Historique des changements et actions, ce qui rend plus facile le travail en collectif et la reproductibilité
  • Des possibilités plus grandes en termes de traitement des données, vis-à-vis des recodages comme des outils statistiques
  • Un dialogue plus simple avec d’autres chercheurs et experts

Mais

  • Un temps d’apprentissage plus long
  • Une installation et “mise en service” qui peuvent décourager les débutants

1.2 Présentation de R

R est un dérivé gratuit (licence GNU GPL) du langage de statistique S. C’est un projet collaboratif et donc ouvert à tous. Il est entretenu par le R Development Core Team (CRAN).

C’est un langage permettant de produire des statistiques descriptives comme des statistiques avancées : tris croisés, tests statistiques, représentations graphiques, analyse factorielle, de réseaux, modélisation, classification, utilisation de données pondérées, cartographie, applications, etc. R permet de développer ses propres fonctions et d’utiliser des fonctions développées par d’autres.

R a de multiples avantages :

  • Gratuit et Open Source, multi-plateformes (Windows, Linux, OS X)
  • Fonctionnalités étendues grâce aux packages (extensions, bibliothèques de fonctions, sorte de “plugin”)
  • Communauté massive, à travers toutes les sciences
  • Fonctionnalités nouvelles et mises à jour régulières
  • Comme tout langage de programmation, permet plus facilement l’historique et la reproductibilité
  • Possibilité de rédiger des documents (comme ce support de formation !) ou produire des applications
  • Compatible avec d’autres langages

Avis très personnel : Par rapport à Python, la communauté de chercheurs de R est plus importante. Plus facile de réaliser des opérations complexes (tests statistiques spécifiques, modélisations).

R a néanmoins quelques inconvénients :

  • Dans le cas de mises à jour des packages (qu’il faut effectuer régulièrement), certaines fonctions peuvent changer
  • Devoir mettre à jour, en plus des packages, R ET RStudio
  • Les packages sont créés par les contributeurs, les syntaxes des fonctions peuvent donc varier
  • Ralentissement quand les données sont très volumineuses
  • Les informations et messages d’erreur peuvent ne pas être évidents à comprendre, mais il existe des forums d’aide très actifs

1.3 Présentation de RStudio

Une console est disponible avec R, mais elle est rudimentaire. On conseille dans ce cas-ci de télécharger un environnement de développement intégré (en anglais IDE, pour Integrated Development Environment). Il y en a plusieurs, le plus courant pour le langage R est RStudio. Ce logiciel est produit par une société à l’origine de nombreuses ressources et projets autour de R (Rmarkdown pour les rapports, shiny pour les applications, tydiverse, etc.).

1.4 Installation

  • D’abord, télécharger le langage R :

Windows : https://cran.r-project.org/ vous sélectionnez Windows, et ensuite base, la version est 4.3.2 Mac : https://cran.r-project.org/ Linux : https://cran.r-project.org/ ou en root dans le terminal : sudo apt-get install r-base r-base-dev [instruction qui n’est pas de moi, je n’ai jamais eu de linux]

1.5 Environnement de RStudio

RStudio offre un éditeur de texte (coloration, auto-complétion, indentation automatique) et un affichage simultané des scripts, sorties, fichiers, graphiques, de l’onglet aide.

  • Console : Retour direct des instructions (sans sauvegarde). La console permet de vérifier que les lignes de commande ont bien été exécutées et d’afficher les messages d’erreur ou d’avertissement.

  • Script : Zone d’écriture des instructions qui constitue le programme (le script) qui sera gardé en mémoire (après sauvegarde).

1.6 Principes de base

1.6.1 Objets et fonctions

R est un langage “orienté objet”. Les actions, réalisées à l’aide de fonctions, agissent sur ces objets. Les fonctions s’écrivent comme ceci : fonction(). A l’intérieur des fonctions (entre les parenthèses), on déclare un ou plusieurs arguments : les objets et des options.

objet<-2023 #on stocke la valeur 2023 dans "objet"
objet #cette ligne affiche le contenu de "objet"
## [1] 2023

Pour les objets : + Respect de la casse + **Ni accent, ni espace, ni caractère spécial en-dehors de l’underscore : “_“.**

Les objets peuvent être de différentes natures : chaîne de caractères (character), chiffre (numeric ou integer), suite d’éléments (vecteur), tableau, matrice, image, graphique, etc. Ils sont toujours créés/modifiés avec “<-”

#Pour afficher l'aide pour une fonction : 
?nom_fonction
#On peut également écrire dans l'onglet "Aide/Help" en bas à droite

1.6.2 Packages

Un package est une extension ajoutée à la session de travail. Les packages sont des bibliothèques de fonctions supplémentaires développées par d’autres personnes. Un package doit être installé (une seule fois) sur l’ordinateur de travail, et ensuite chargé.

Les packages dits “officiels” sont validés par la communauté de R (CRAN). Leur documentation est disponible sur leur site web : cran.r-project.org.

Quand les packages sont “officiels”, c’est-à-dire approuvés par le CRAN, on peut saisir la ligne de commande suivante :

install.packages("tidyverse") #Rappel : on n'installe un package qu'une seule fois
install.packages("questionr") #Le plus pratique est d'écrire cette ligne dans la console, si c'est une ligne de commande dans un script, RStudio va peut-être essayer de réinstaller le package. 

On peut également passer par l’onglet Tools du menu et Install packages, et enfin saisir le nom du package en question.

Quand les packages n’ont pas été approuvés par le CRAN, on peut saisir la ligne de commande suivante :

devtools::install_github("utilisateur/nomPackage") #nous n'utiliserons pas cette ligne aujourd'hui

⚠ Il peut y avoir des problèmes de compatibilité entre les versions des packages et la version de R.

Ensuite, pour charger un package, il suffira d’utiliser la commande library(), comme ceci :

library(tidyverse)

1.7 Organisation du travail

1.7.1 Création d’un projet

Créer un projet permet de garder l’ensemble des documents, scripts, etc., réalisés. Grâce aux projets, il n’y a pas besoin d’exécuter le script à chaque ouverture de RStudio.

On crée un dossier, qui sera directement relié au projet. La bonne pratique est sauvegarder l’ensemble des scripts dans ce dossier, avec un sous-dossier “Données” ou “Data”. C’est particulièrement utile si l’on mène plusieurs recherches en même temps.

Deux moyens de créer un projet : 1. le cube bleu en haut à gauche, ou 2. dans File, sélectionnez New Project.... Pour ouvrir par la suite la session, il suffira de cliquer sur le fichier .Rproj.

1.7.2 Utilisation de commentaires

Les commentaires permettent de mieux comprendre et d’organiser les lignes de commandes.

Pour écrire un commentaire, il suffit de précéder le texte de #, le logiciel n’exécute pas la ligne en question. Pour passer un texte sélectionné en commentaire (et inversement) : Ctrl + Shift + C. On peut également inclure des titres dans le script, comme ceci :

# Titre ---- 
  # voir le bouton "outline" en haut à droite du script

2. Importation des données

Rappel : La base que nous allons utiliser porte sur les principaux établissements d’enseignement supérieur. Elle est produite par le Ministère de l’Enseignement Supérieur et de la Recherche et originellement téléchargeable sur : https://data.enseignementsup-recherche.gouv.fr/explore/dataset/fr-esr-principaux-etablissements-enseignement-superieur/export/?flg=fr-fr&disjunctive.type_d_etablissement&disjunctive.typologie_d_universites_et_assimiles.

Vous pouvez télécharger la version que nous utiliserons aujourd’hui sur : https://github.com/lisa-wt/PUDL_R_2025

Pour des analyses de ces bases, voir le github de Julien Gossa : https://github.com/cpesr/tdbESR-rapport.

2.1 Importer des données

En général, on ne crée pas directement la base dans R. La base est souvent dans un fichier qu’on importe dans R en créant un nouvel objet.

Le fichier source peut être en format :

  • Texte (.txt, .csv),
  • Tableur : Excel (xls, xlsx), Calc (.ods),
  • Fichier adapté à d’autres logiciels statistiques : SAS (.sas7bdat), SPSS (sav),
  • Format R : (.RData)
  • Ou encore html, xml, json, etc.

Nous ne traiterons que des formats les plus courants : notamment .csv et .xlsx.

2.1.1 Importer des fichiers textes

La grande majorité des bases de données sont en format .csv (comme celles sur lesquelles nous travaillerons aujourd’hui).

nom_table <-read.csv("Sous_dossier/Fichier.csv", stringsAsFactors = F)
#Le chemin d'accès est un argument nécessaire : "Sous-dossier/Fichier.csv". Parce que nous sommes au sein d'un projet, le chemin débute à partir du dossier lié au projet.
#arguments utiles :
# - stringsAsFactors = F ; ne pas transformer les chaînes de caractères en facteurs
# - fileEncoding = format d'encodage des caractères
# - header = TRUE/FALSE : La première ligne correspond-elle aux titres des variables ?
#pour voir davantage d'arguments (options), voir l'onglet Aide/Help

Quelques subtilités existent pour l’importation d’un .csv ; on utilise…

  • read.csv quand le séparateur est une ,
  • read.csv2 quand le séparateur est un ;
  • read.table pour les fichiers .txt et séparateur = \t

Importons la base sur laquelle nous allons travailler :

etab<-read.csv2("Data/fr-esr-principaux-etablissements-enseignement-superieur_R.csv", stringsAsFactors = F, na.strings = "")

#le séparateur pour cette base est un ";"
#en cas de problème d'encodage, nous aurions pu utiliser ajuster l'argument "fileEncoding"

2.1.2 Importer des fichiers tableurs

Plusieurs packages facilitent l’importation directe de tableaux de données enregistrés dans divers formats.

Pour les fichiers excel (.xlsx ou .xls), il est possible d’utiliser les packages openxlsx ou readxl.

library(readxl) #il y a également le package openxlsx avec la fonction read.xlsx()
nom_base<-read_excel("Fichier.xlsx", sheet = index_de_la_feuille)

Pour les fichiers .ods, il est possible d’utiliser la fonction read_ods du package readODS :

library(readODS) #après avoir installé ce package
nom_base<-read_ods("Fichier.ods", sheet = index_de_la_feuille)

2.2 Exporter des données

La base peut être exportée sous plusieurs formats : le format .rds (format R), .RData (pour l’ensemble de l’environnement en réalité, votre projet), ou encore sous format .csv. Pour ce dernier :

write.csv2(nom_de_la_base, "nom_fichier.csv", fileEncoding = "UTF-8", na="", row.names = F)

2.3 Dictionnaire des codes et bonnes pratiques

  • identifiant_interne = identifiant unique, code alphanumérique
  • type.d.établissement = Université, Ecole, Grand établissement, Autre établissement
  • secteur_d_etablissement = Public, Privé
  • dep_nom
  • Région
  • Les effectifs d’étudiants inscrits, pour les années universitaires :
    • 2010-11
    • 2011-12
    • 2012-13
    • 2013-14
    • 2014-15
    • 2015-16
    • 2016-17
    • 2017-18
  • La possession d’un compte Linkedin, Twitter, etc.

Dans le cas où l’on crée soi-même sa base de données, quelques règles d’usage sont idéalement à respecter (à mettre en lien avec la création du questionnaire) :

Les noms des colonnes, c’est-à-dire des variables, doivent décrire le contenu, ne pas commencer par un chiffre, ne pas être trop long ni ne comporter d’espace ou d’accent (SEXE vs SEXE DE L’ENQUÊTÉ). On préfèrera à l’espace l’underscore : _. Tous les noms des variables doivent être dans la même langue. Les noms des variables doivent être cohérents : de préférence, on n’écrira pas DIPLOME_CONJOINT et PCS_CJ. De la même manière, il ne faut pas avoir deux variables identiques dont la seule différence est la casse (l’une en minuscule, l’autre en majuscule).

Les modalités (réponses) sont codées en chiffres. On se réfèrera au dictionnaire des codes pour comprendre la signification de chacun d’entre eux. Certaines règles d’usage peuvent être notées : par exemple, pour la variable SEXE, le 1 signifie “homme”, le 2 signifie “femme” ; le “oui” = 1 et “non” = 2. Certains découpages, on pensera notamment au DIPLOME, sont globalement uniformisés.

2.4 Décrire le tableau

2.4.1 Dimensions du tableau et noms des variables

Un tableau de données (data.frame) est un objet en deux dimensions (des lignes et des colonnes).

etab[1:2,1:2] # Présente les deux premières lignes et deux premières colonnes du tableau
head(etab, 10) #10 premières observations
names(etab) #Noms des colonnes
##   [1] "identifiant_interne"                    
##   [2] "Libellé"                                
##   [3] "nom_court"                              
##   [4] "sigle"                                  
##   [5] "type.d.établissement"                   
##   [6] "typologie_d_universites_et_assimiles"   
##   [7] "secteur_d_etablissement"                
##   [8] "vague_contractuelle"                    
##   [9] "localisation"                           
##  [10] "Site.internet"                          
##  [11] "Géolocalisation"                        
##  [12] "uai...identifiant"                      
##  [13] "siret"                                  
##  [14] "siren"                                  
##  [15] "rna"                                    
##  [16] "Identifiant.wikidata"                   
##  [17] "Elément.wikidata"                       
##  [18] "identifiant_idref"                      
##  [19] "Identifiant.ETER"                       
##  [20] "Identifiant.ROR"                        
##  [21] "Elément.ROR"                            
##  [22] "Identifiant.GRID"                       
##  [23] "Elément.GRID"                           
##  [24] "Identifiant.PIC"                        
##  [25] "Identifiant.OrgRef"                     
##  [26] "Identifiant.ISNI"                       
##  [27] "Elément.ISNI"                           
##  [28] "identifiant_funding_data"               
##  [29] "Elément.Funding.Data"                   
##  [30] "identifiant_dataesr"                    
##  [31] "anciens_codes_uai"                      
##  [32] "rattachement_identifiants"              
##  [33] "rattachement"                           
##  [34] "association_identifiants"               
##  [35] "association"                            
##  [36] "date_creation"                          
##  [37] "texte_de_ref_creation_lib"              
##  [38] "texte_de_ref_creation"                  
##  [39] "date_fermeture"                         
##  [40] "texte_de_ref_fermeture_lib"             
##  [41] "texte_de_ref_fermeture"                 
##  [42] "dernier_decret_legifrance_lib"          
##  [43] "dernier_decret_legifrance"              
##  [44] "Code.commune"                           
##  [45] "Commune"                                
##  [46] "Code.unité.urbaine"                     
##  [47] "Unité.urbaine"                          
##  [48] "Code.département"                       
##  [49] "Département"                            
##  [50] "Code.académie"                          
##  [51] "Académie"                               
##  [52] "Code.région"                            
##  [53] "Région"                                 
##  [54] "Ancien.code.région"                     
##  [55] "Ancienne.région"                        
##  [56] "Mention.distribution"                   
##  [57] "Adresse"                                
##  [58] "Lieu.dit"                               
##  [59] "Boite.postale"                          
##  [60] "Code.postal"                            
##  [61] "Localité"                               
##  [62] "Pays"                                   
##  [63] "Numéro.de.téléphone"                    
##  [64] "statut_juridique_court"                 
##  [65] "Statut.juridique"                       
##  [66] "qualification_court"                    
##  [67] "Qualification"                          
##  [68] "compte_facebook"                        
##  [69] "compte_twitter"                         
##  [70] "compte_instagram"                       
##  [71] "compte_flickr"                          
##  [72] "compte_pinterest"                       
##  [73] "flux_rss"                               
##  [74] "compte_linkedin"                        
##  [75] "compte_viadeo"                          
##  [76] "compte_france_culture"                  
##  [77] "compte_scribd"                          
##  [78] "compte_scoopit"                         
##  [79] "compte_tumblr"                          
##  [80] "compte_youtube"                         
##  [81] "compte_vimeo"                           
##  [82] "compte_dailymotion"                     
##  [83] "autres"                                 
##  [84] "compte_gitHub"                          
##  [85] "Page.Wikipédia.en.français"             
##  [86] "Page.Wikipédia.en.anglais"              
##  [87] "scanr"                                  
##  [88] "hal"                                    
##  [89] "mooc"                                   
##  [90] "article"                                
##  [91] "uo_lib_officiel"                        
##  [92] "English.name"                           
##  [93] "Site.internet.en.anglais"               
##  [94] "Site.internet.en.chinois"               
##  [95] "Site.internet.en.espagnol"              
##  [96] "Site.internet.en.allemand"              
##  [97] "Site.internet.en.italien"               
##  [98] "Effectifs.d.étudiants.inscrits.2010.11" 
##  [99] "Effectifs.d.étudiants.inscrits.2011.12" 
## [100] "Effectifs.d.étudiants.inscrits.2012.13" 
## [101] "Effectifs.d.étudiants.inscrits.2013.14" 
## [102] "Effectifs.d.étudiants.inscrits.2014.15" 
## [103] "Effectifs.d.étudiants.inscrits.2015.16" 
## [104] "Effectifs.d.étudiants.inscrits.2016.17" 
## [105] "Effectifs.d.étudiants.inscrits.2017.18" 
## [106] "uai_rgp_loi_esr_2013"                   
## [107] "universites_fusionnees"                 
## [108] "etablissement_experimental"             
## [109] "champ_recherche"                        
## [110] "implantations"                          
## [111] "identifiant_programmes_lolf"            
## [112] "statut_operateur_lolf"                  
## [113] "libelle_missions_lolf"                  
## [114] "libelle_programmes_lolf"                
## [115] "libelle_programme_lolf_chef_de_file"    
## [116] "identifiants_autres_programmes_lolf"    
## [117] "libelles_autres_programmes_lolf"        
## [118] "identifiant_programme_lolf_chef_de_file"
## [119] "libelle_mission_chef_de_file"           
## [120] "compte_googleplus"
names(etab)[1:10] #Noms des 10 premières colonnes
##  [1] "identifiant_interne"                 
##  [2] "Libellé"                             
##  [3] "nom_court"                           
##  [4] "sigle"                               
##  [5] "type.d.établissement"                
##  [6] "typologie_d_universites_et_assimiles"
##  [7] "secteur_d_etablissement"             
##  [8] "vague_contractuelle"                 
##  [9] "localisation"                        
## [10] "Site.internet"

Le package skimr possède une fonction skim donnent un résumé de la BDD :

library(skimr)
skim(etab)
Data summary
Name etab
Number of rows 250
Number of columns 120
_______________________
Column type frequency:
character 88
logical 23
numeric 9
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
identifiant_interne 0 1.00 5 5 0 250 0
Libellé 0 1.00 3 150 0 250 0
nom_court 112 0.55 2 25 0 138 0
sigle 140 0.44 2 20 0 109 0
type.d.établissement 0 1.00 2 6 0 4 0
typologie_d_universites_et_assimiles 183 0.27 38 51 0 5 0
vague_contractuelle 74 0.70 7 7 0 5 0
localisation 0 1.00 8 75 0 130 0
Site.internet 2 0.99 15 83 0 248 0
Géolocalisation 0 1.00 12 28 0 249 0
uai…identifiant 3 0.99 8 8 0 247 0
rna 213 0.15 10 10 0 37 0
Identifiant.wikidata 13 0.95 5 10 0 237 0
Elément.wikidata 13 0.95 37 42 0 237 0
identifiant_idref 101 0.60 8 9 0 149 0
Identifiant.ETER 88 0.65 6 6 0 162 0
Identifiant.ROR 51 0.80 9 9 0 199 0
Elément.ROR 51 0.80 25 25 0 199 0
Identifiant.GRID 52 0.79 11 13 0 198 0
Identifiant.ISNI 88 0.65 19 19 0 162 0
Elément.ISNI 88 0.65 36 36 0 162 0
identifiant_dataesr 249 0.00 14 14 0 1 0
anciens_codes_uai 3 0.99 8 17 0 247 0
texte_de_ref_creation_lib 160 0.36 36 283 0 68 0
texte_de_ref_creation 166 0.34 60 60 0 61 0
dernier_decret_legifrance_lib 46 0.82 61 334 0 110 0
dernier_decret_legifrance 46 0.82 60 60 0 110 0
Code.commune 0 1.00 4 5 0 133 0
Commune 0 1.00 3 24 0 132 0
Code.unité.urbaine 4 0.98 7 8 0 65 0
Unité.urbaine 4 0.98 3 25 0 65 0
Code.département 0 1.00 4 4 0 62 0
Département 0 1.00 3 21 0 65 0
Code.académie 4 0.98 3 3 0 32 0
Académie 4 0.98 4 19 0 32 0
Code.région 0 1.00 3 3 0 19 0
Région 0 1.00 5 26 0 19 0
Ancien.code.région 6 0.98 3 3 0 26 0
Ancienne.région 6 0.98 5 26 0 26 0
Mention.distribution 223 0.11 8 48 0 25 0
Adresse 5 0.98 11 39 0 243 0
Lieu.dit 237 0.05 8 35 0 13 0
Boite.postale 165 0.34 5 23 0 85 0
Localité 0 1.00 4 30 0 196 0
Pays 0 1.00 5 7 0 5 0
statut_juridique_court 0 1.00 3 93 0 13 0
Statut.juridique 0 1.00 9 93 0 14 0
qualification_court 192 0.23 6 6 0 1 0
Qualification 192 0.23 62 62 0 1 0
compte_facebook 37 0.85 30 110 0 213 0
compte_twitter 46 0.82 24 58 0 204 0
compte_instagram 127 0.49 31 56 0 123 0
compte_flickr 233 0.07 35 54 0 17 0
compte_pinterest 245 0.02 31 40 0 5 0
flux_rss 160 0.36 22 255 0 90 0
compte_linkedin 108 0.57 37 117 0 142 0
compte_france_culture 243 0.03 61 84 0 7 0
compte_scribd 249 0.00 59 59 0 1 0
compte_scoopit 243 0.03 30 67 0 7 0
compte_tumblr 247 0.01 28 36 0 3 0
compte_youtube 89 0.64 30 75 0 160 0
compte_vimeo 240 0.04 23 34 0 10 0
compte_dailymotion 244 0.02 32 58 0 6 0
compte_gitHub 247 0.01 26 29 0 3 0
Page.Wikipédia.en.français 22 0.91 37 178 0 228 0
Page.Wikipédia.en.anglais 34 0.86 35 176 0 216 0
scanr 86 0.66 63 64 0 164 0
hal 175 0.30 19 63 0 75 0
mooc 225 0.10 41 81 0 25 0
article 8 0.97 1 7 0 5 0
uo_lib_officiel 0 1.00 5 125 0 250 0
English.name 143 0.43 4 85 0 107 0
Site.internet.en.anglais 125 0.50 18 84 0 125 0
Site.internet.en.chinois 240 0.04 20 43 0 10 0
Site.internet.en.espagnol 230 0.08 20 80 0 20 0
Site.internet.en.allemand 246 0.02 29 48 0 4 0
Effectifs.d.étudiants.inscrits.2010.11 87 0.65 2 6 0 154 0
Effectifs.d.étudiants.inscrits.2011.12 86 0.66 2 6 0 152 0
Effectifs.d.étudiants.inscrits.2012.13 84 0.66 2 6 0 156 0
Effectifs.d.étudiants.inscrits.2013.14 84 0.66 2 6 0 157 0
Effectifs.d.étudiants.inscrits.2014.15 82 0.67 2 6 0 157 0
Effectifs.d.étudiants.inscrits.2015.16 82 0.67 2 6 0 154 0
Effectifs.d.étudiants.inscrits.2016.17 82 0.67 2 6 0 155 0
Effectifs.d.étudiants.inscrits.2017.18 82 0.67 2 6 0 158 0
uai_rgp_loi_esr_2013 103 0.59 8 35 0 33 0
universites_fusionnees 245 0.02 3 3 0 1 0
etablissement_experimental 235 0.06 3 3 0 1 0
champ_recherche 0 1.00 28 615 0 250 0

Variable type: logical

skim_variable n_missing complete_rate mean count
Elément.GRID 250 0 NaN :
identifiant_funding_data 250 0 NaN :
rattachement_identifiants 250 0 NaN :
rattachement 250 0 NaN :
association_identifiants 250 0 NaN :
association 250 0 NaN :
date_fermeture 250 0 NaN :
texte_de_ref_fermeture_lib 250 0 NaN :
texte_de_ref_fermeture 250 0 NaN :
compte_viadeo 250 0 NaN :
autres 250 0 NaN :
Site.internet.en.italien 250 0 NaN :
implantations 250 0 NaN :
identifiant_programmes_lolf 250 0 NaN :
statut_operateur_lolf 250 0 NaN :
libelle_missions_lolf 250 0 NaN :
libelle_programmes_lolf 250 0 NaN :
libelle_programme_lolf_chef_de_file 250 0 NaN :
identifiants_autres_programmes_lolf 250 0 NaN :
libelles_autres_programmes_lolf 250 0 NaN :
identifiant_programme_lolf_chef_de_file 250 0 NaN :
libelle_mission_chef_de_file 250 0 NaN :
compte_googleplus 250 0 NaN :

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
secteur_d_etablissement 0 1.00 1.340000e+00 4.800000e-01 1.000000e+00 1.000000e+00 1.000000e+00 2.000000e+00 2.000000e+00 ▇▁▁▁▅
siret 5 0.98 3.229388e+13 2.357463e+13 1.300000e+13 1.930000e+13 1.980000e+13 3.890000e+13 8.980000e+13 ▇▂▁▁▂
siren 5 0.98 3.228905e+08 2.357246e+08 1.300004e+08 1.925122e+08 1.975350e+08 3.885916e+08 8.981921e+08 ▇▂▁▁▂
Identifiant.PIC 156 0.38 9.770080e+08 3.550671e+07 8.918781e+08 9.536313e+08 9.982418e+08 9.998502e+08 9.999562e+08 ▂▁▁▁▇
Identifiant.OrgRef 138 0.45 1.267594e+07 1.159343e+07 6.844700e+04 3.835740e+06 1.099096e+07 1.395846e+07 4.700244e+07 ▇▆▂▁▁
Elément.Funding.Data 232 0.07 4.453444e+11 1.619815e+11 1.000090e+08 5.010000e+11 5.010000e+11 5.010000e+11 5.010000e+11 ▁▁▁▁▇
date_creation 37 0.85 1.956390e+03 7.440000e+01 1.431000e+03 1.948000e+03 1.972000e+03 1.996000e+03 2.023000e+03 ▁▁▁▁▇
Code.postal 0 1.00 6.157999e+04 2.542458e+04 1.860000e+02 3.517000e+04 6.935300e+04 7.739125e+04 9.885100e+04 ▂▃▂▇▅
Numéro.de.téléphone 82 0.67 3.125348e+08 1.500695e+08 1.307362e+08 1.549393e+08 2.980475e+08 4.720804e+08 5.942979e+08 ▇▅▅▃▃

2.4.2 Types de variables

Il existe différents types de variables : numeric, character, integer, factor, logical.

La commande str donne le type d’objet (ici data.frame), le nom de chaque variable, son type et un aperçu de chacune d’elle :

str(etab)

Si on ne souhaite connaître que le type d’une seule variable, on peut utiliser la commande class :

class(etab$secteur_d_etablissement)
## [1] "integer"

2.5 Les opérateurs

Les opérateurs :

  • <- : marque l’assignation, création d’élément, stocker dans un objet
  • == : Egalité (A == B signifie “A est égal à B”)
  • != : Exclusion ( A != B signifie “A est différent de B”)
  • < : inférieur ||| <= : inférieur ou égal ||| > : supérieur ||| >= : supérieur ou égal
  • %in% : appartient à

Lorsque l’on souhaite enchaîner plusieurs conditions, on utilise :

  • Pour le OU : |
  • Pour le ET : &

Autres fonctions :

  • c(1,2) : suite d’éléments (création de vecteur)
  • 1:5 : Suite de nombres allant de 1 à 5
  • seq(0,20,2) : Suite de nombre allant de 0 à 20 avec un pas de 5
  • rm(objet) : Suppression d’un objet

2.6 Quelques fonctions pratiques

2.6.1 Modifier le nom des colonnes

Il est possible de modifier les noms des colonnes avec la fonction rename :

base <- rename(etab, nouveau_nom = ancien_nom) #le nouveau nom se trouve à gauche, l'ancien nom à droite. On peut y ajouter d'autres variables en les séparant d'une ",".

Lorsqu’on possède une base un peu “sale”, il existe de nombreuses fonctions pour aider à nettoyer, à la rendre plus facilement traitable. Avec le package janitor, vous avez notamment accès à la fonction clean_names(), qui permet de nettoyer tous les noms de colonnes en snake_case (c’est-à-dire en minuscules, avec underscore et sans caractères spéciaux) :

# on installe le package
install.packages("janitor")
# puis on le charge
library(janitor)
etab<-clean_names(etab)

3. Recodages simples de variables

Les données provenant d’enquêtes sont la majeure partie du temps codées : elles sont souvent représentées par des chiffres (variable SEXE, 1=Homme, 2=Femme, voir le dictionnaire des codes). Les BDD sont ainsi moins lourdes et comportent moins d’erreurs. Une partie significative du temps consacré à l’exploitation de données quantitatives consiste en réalité en du nettoyage et du recodage. On peut recoder afin de rendre les résultats effectués par la suite plus lisibles et compréhensibles, ou encore afin de croiser des variables par exemple.

3.1 Recodage de modalités

Il est courant d’explorer visuellement la BDD et de lire, au moins en partie, le dictionnaire des codes et le questionnaire afin d’identifier les variables intéressantes. Imaginons que nous souhaitions obtenir une idée rapide de la répartition du secteur (public/privé) au sein des établissements de notre base. Pour explorer la répartition des réponses sur une variable, un des moyens les plus simples est d’utiliser la fonction freq provenant du package questionr. Une alternative R-base (c’est-à-dire disponible sans le chargement de packages spécifiques) est l’instruction table, mais cette dernière doit être combinée avec d’autres fonctions pour donner autant d’indications que celle de freq.

library(questionr) #on charge le package
freq(etab$secteur_d_etablissement)

Il existe toujours plusieurs manières de coder une même action. Ici, pour le recodage simple, vous trouverez deux méthodes : ce qu’on appelle le R-base (ne nécessite aucun package) et la fonction fct_collapse().

Nous souhaitons recoder la variable secteur_d_etablissement pour qu’elle affiche une modalité compréhensible. Cette variable est de type integer (chiffre entier) et possède deux modalités : 1 et 2. Le 1 correspondant à la réponse “Public”, le 2 “Privé”.

etab$secteur_d_etablissement_r<-NA
etab$secteur_d_etablissement_r[etab$secteur_d_etablissement==1]<-"Public"
etab$secteur_d_etablissement_r[etab$secteur_d_etablissement==2]<-"Privé"

On examine le résultat :

freq(etab$secteur_d_etablissement_r)

Tout est bon !

Une autre manière de recoder ces modalités est la fonction fct_collapse (package forcats, automatiquement chargé lorsque vous chargez le package tidyverse). Elle permet de recoder des modalités. Certaines opérations exigent que la donnée soit d’un type spécifique, c’est le cas ici puisque cette fonction ne peut s’effectuer que sur une variable de type factor.

Pour factoriser une variable, on peut le faire comme ceci :

etab$secteur_d_etablissement<-factor(etab$secteur_d_etablissement)
#Il est nécessaire d'indiquer, avec la flèche (assignation), qu'on réalise une action sur cette variable
#On peut vérifier le type de la variable : 
class(etab$secteur_d_etablissement)
## [1] "factor"
etab$secteur_d_etablissement<-fct_collapse(etab$secteur_d_etablissement,
             "Public"=1,
             "Privé"=2)

Pour minimiser le nombre de lignes de code, il est possible de combiner les fonctions :

etab$secteur_d_etablissement<-fct_collapse(factor(etab$secteur_d_etablissement),
             "Public"=1,
             "Privé"=2)

Le type de la variable peut donc être changé assez facilement :

  • Pour transformer en variable de type numeric : nom_base$nom_variable<-as.numeric(nom_base$nom_variable)
  • Pour transformer en variable de type character (chaînes de) : nom_base$nom_variable<-as.character(nom_base$nom_variable)
  • Pour transformer en variable de type factor : nom_base$nom_variable<-factor(nom_base$nom_variable)
  • Pour transformer en variable de type integer : nom_base$nom_variable<-as.integer(nom_base$nom_variable)
  • Pour transformer en variable de type logical : nom_base$nom_variable<-as.logical(nom_base$nom_variable)

⚠ Toujours vérifier avant et après la répartition des réponses, en particulier s’il y a de multiples changements sur une même variable (passer une variable numérique en factor sans changement des modalités, puis de nouveau en numérique).

freq(etab$secteur_d_etablissement)
unique(etab$secteur_d_etablissement) #renvoie les modalités possibles
## [1] Public Privé 
## Levels: Public Privé

Mise en pratique : Recodons la variable type_d_etablissement avec la commande fct_collapse. Les modalités : Un = Université ; Deux = Ecole ; Trois = Grand établissement ; Quatre = Autre établissement.

etab$type_d_etablissement_r<-fct_collapse(factor(etab$type_d_etablissement),
             "Université"="Un",
             "Ecole"="Deux",
             "Grand établissement"="Trois",
             "Autre établissement"="Quatre")

3.2 Recodage par calcul

On peut ainsi créer une variable numérique détaillant l’ancienneté de l’établissement, à partir de la date_creation :

#En se basant sur 2018, la dernière année universitaire (2017-2018) pour laquelle les effectifs d'étudiants inscrits sont connus : 
etab$anciennete<-2018 - etab$date_creation

4. Statistiques descriptives

4.1 Statistiques univariées

4.1.1 Représenter une variable numérique : indices de répartition

Pour les variables qualitatives, nous avons introduit plus tôt la commande freq.

freq(etab$type_etab, 
     sort="dec",total=T)
# sort = "dec" pour trier par ordre décroissant
# cum = T pour les pourcentages cumulés, total = T pour avoir le total
# valid = F pour enlever la colonne val%

Elle permet de déterminer la répartition des réponses pour des variables qualitatives. Pour des variables quantitatives, d’autres commandes sont plus appropriées :

summary(etab$effectifs_d_etudiants_inscrits_2017_18)
##    Length     Class      Mode 
##       250 character character

La commande ci-dessus ne fonctionne pas, en cause : la variable n’est pas numérique. En effet, des espaces ont été ajoutés à la création de la base pour séparer les milliers et la variable comprend une modalité “nd” (non disponible). Changer le type de la variable immédiatement ne fonctionnerait pas : tous les chiffres avec un espace seraient changés en NAs. Il faut d’abord supprimer ces espaces. La fonction gsub permet de rechercher une chaîne de caractères (argument 1) et de la remplacer (argument 2) au sein d’une variable de la base (argument 3). Il faut ensuite la changer en variable numérique.

etab$effectifs_d_etudiants_inscrits_2017_18 <- gsub(" ","", etab$effectifs_d_etudiants_inscrits_2017_18)
etab$effectifs_d_etudiants_inscrits_2017_18 <- as.numeric(etab$effectifs_d_etudiants_inscrits_2017_18)
#Vous devriez recevoir dans votre console un message. Des NAs ont effectivement été introduits : les modalités "nd" (pour "non disponible") et les cellules vides se transformeront en réels NAs.

La commande summary fonctionne désormais :

summary(etab$effectifs_d_etudiants_inscrits_2017_18)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##      81    1029    3025    8685   10112   63948      92
#Pour ces informations une à une : 

# mean(nom_base$nom_variable, na.rm=T)
# median(nom_base$nom_variable, na.rm=T)
# max(nom_base$nom_variable, na.rm=T)
# min(nom_base$nom_variable, na.rm=T)

L’écart-type est néanmoins absent, il est possible de l’obtenir en utilisant la fonction sd, l’argument na.rm = T correspond à la suppression des NAs, sans quoi R ne peut pas calculer l’écart-type.

sd(etab$effectifs_d_etudiants_inscrits_2017_18, na.rm=T)
## [1] 12398.91

Mise en pratique : Effectuons un summary pour les effectifs d’étudiants inscrits pour l’année universitaire 2010-2011.

#Comme pour la variable précédente, il faut d'abord supprimer les espaces, sans quoi des NAs seraient introduits à la place des chiffres en comportant.
etab$effectifs_d_etudiants_inscrits_2010_11 <- gsub(" ","", etab$effectifs_d_etudiants_inscrits_2010_11)
etab$effectifs_d_etudiants_inscrits_2010_11 <- as.numeric(etab$effectifs_d_etudiants_inscrits_2010_11)
#Les NAs introduits remplacent les "nd" (non disponible).
summary(etab$effectifs_d_etudiants_inscrits_2010_11)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##      57     706    2528    7843   10848   63641      97

4.2 Statistiques bivariées

4.2.1 Croiser des variables catégorielles

Effectifs bruts :

table(etab$region, etab$secteur_d_etablissement, useNA = "ifany")
##                             
##                              Public Privé
##   Auvergne-Rhône-Alpes           16     5
##   Bourgogne-Franche-Comté         4     2
##   Bretagne                        8     5
##   Centre-Val de Loire             3     0
##   Collectivités d'outre-mer       2     0
##   Corse                           1     0
##   Étranger                        4     0
##   Grand Est                      11     5
##   Guadeloupe                      1     0
##   Guyane                          1     0
##   Hauts-de-France                 8    10
##   Île-de-France                  53    33
##   La Réunion                      1     0
##   Mayotte                         1     0
##   Normandie                       9     4
##   Nouvelle-Aquitaine             10     5
##   Occitanie                      20     4
##   Pays de la Loire                4    11
##   Provence-Alpes-Côte d'Azur      7     2

Ajout des marges :

addmargins(
  table(etab$region, etab$secteur_d_etablissement, useNA = "ifany")
  )
##                             
##                              Public Privé Sum
##   Auvergne-Rhône-Alpes           16     5  21
##   Bourgogne-Franche-Comté         4     2   6
##   Bretagne                        8     5  13
##   Centre-Val de Loire             3     0   3
##   Collectivités d'outre-mer       2     0   2
##   Corse                           1     0   1
##   Étranger                        4     0   4
##   Grand Est                      11     5  16
##   Guadeloupe                      1     0   1
##   Guyane                          1     0   1
##   Hauts-de-France                 8    10  18
##   Île-de-France                  53    33  86
##   La Réunion                      1     0   1
##   Mayotte                         1     0   1
##   Normandie                       9     4  13
##   Nouvelle-Aquitaine             10     5  15
##   Occitanie                      20     4  24
##   Pays de la Loire                4    11  15
##   Provence-Alpes-Côte d'Azur      7     2   9
##   Sum                           164    86 250

Avec le package questionr, il est possible d’utiliser la commande rprop pour obtenir les pourcentages en ligne, cprop pour les pourcentages en colonne et prop pour les pourcentages totaux.

rprop(table(etab$region, etab$secteur_d_etablissement, useNA = "ifany"))
##                             
##                              Public Privé Total
##   Auvergne-Rhône-Alpes        76.2   23.8 100.0
##   Bourgogne-Franche-Comté     66.7   33.3 100.0
##   Bretagne                    61.5   38.5 100.0
##   Centre-Val de Loire        100.0    0.0 100.0
##   Collectivités d'outre-mer  100.0    0.0 100.0
##   Corse                      100.0    0.0 100.0
##   Étranger                   100.0    0.0 100.0
##   Grand Est                   68.8   31.2 100.0
##   Guadeloupe                 100.0    0.0 100.0
##   Guyane                     100.0    0.0 100.0
##   Hauts-de-France             44.4   55.6 100.0
##   Île-de-France               61.6   38.4 100.0
##   La Réunion                 100.0    0.0 100.0
##   Mayotte                    100.0    0.0 100.0
##   Normandie                   69.2   30.8 100.0
##   Nouvelle-Aquitaine          66.7   33.3 100.0
##   Occitanie                   83.3   16.7 100.0
##   Pays de la Loire            26.7   73.3 100.0
##   Provence-Alpes-Côte d'Azur  77.8   22.2 100.0
##   Ensemble                    65.6   34.4 100.0

Mise en pratique : Réalisons un tri croisé des variables Région et etablissement_experimental, avec les pourcentages en colonnes.

cprop(table(etab$region, etab$etablissement_experimental, useNA = "ifany"))
##                             
##                              Oui   <NA>  Ensemble
##   Auvergne-Rhône-Alpes        13.3   8.1   8.4   
##   Bourgogne-Franche-Comté      0.0   2.6   2.4   
##   Bretagne                     6.7   5.1   5.2   
##   Centre-Val de Loire          0.0   1.3   1.2   
##   Collectivités d'outre-mer    0.0   0.9   0.8   
##   Corse                        0.0   0.4   0.4   
##   Étranger                     0.0   1.7   1.6   
##   Grand Est                    0.0   6.8   6.4   
##   Guadeloupe                   0.0   0.4   0.4   
##   Guyane                       0.0   0.4   0.4   
##   Hauts-de-France             13.3   6.8   7.2   
##   Île-de-France               40.0  34.0  34.4   
##   La Réunion                   0.0   0.4   0.4   
##   Mayotte                      0.0   0.4   0.4   
##   Normandie                    0.0   5.5   5.2   
##   Nouvelle-Aquitaine           0.0   6.4   6.0   
##   Occitanie                   13.3   9.4   9.6   
##   Pays de la Loire             6.7   6.0   6.0   
##   Provence-Alpes-Côte d'Azur   6.7   3.4   3.6   
##   Total                      100.0 100.0 100.0

Version R-base :

prop.table(
  table(etab$region, etab$secteur_d_etablissement, useNA="ifany")
  , 1)*100
##                             
##                                 Public     Privé
##   Auvergne-Rhône-Alpes        76.19048  23.80952
##   Bourgogne-Franche-Comté     66.66667  33.33333
##   Bretagne                    61.53846  38.46154
##   Centre-Val de Loire        100.00000   0.00000
##   Collectivités d'outre-mer  100.00000   0.00000
##   Corse                      100.00000   0.00000
##   Étranger                   100.00000   0.00000
##   Grand Est                   68.75000  31.25000
##   Guadeloupe                 100.00000   0.00000
##   Guyane                     100.00000   0.00000
##   Hauts-de-France             44.44444  55.55556
##   Île-de-France               61.62791  38.37209
##   La Réunion                 100.00000   0.00000
##   Mayotte                    100.00000   0.00000
##   Normandie                   69.23077  30.76923
##   Nouvelle-Aquitaine          66.66667  33.33333
##   Occitanie                   83.33333  16.66667
##   Pays de la Loire            26.66667  73.33333
##   Provence-Alpes-Côte d'Azur  77.77778  22.22222
# l'argument aurait été 2 pour avoir les pourcentages en colonnes. 

4.2.2 Les indices de répartition par groupes : le tapply

Afin d’obtenir les indicateurs de répartition selon certains critères, on utilise ce qu’on appelle des “group by”. Pour l’instant, voici une façon simple sur R de calculer des indices de répartition pour une variable quantitative en fonction des modalités d’une variable catégorielle. Par exemple, je veux en savoir plus sur la répartition des effectifs en fonction du statut (public/privé) de l’établissement :

tapply(etab$effectifs_d_etudiants_inscrits_2017_18, etab$secteur_d_etablissement_r, summary)
## $Privé
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##    81.0   966.2  1584.5  2741.2  3772.5 14510.0      26 
## 
## $Public
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##     183    1112    6451   12324   20376   63948      66
# ordre : la var quanti, la var catégorielle, et enfin la fonction que je veux appliquer à travers les groupes de la var catégorielle

4.3 Le package gtsummary

# Après avoir installé le package gtsummary avec install.packages("gtsummary")
library(gtsummary)

La fonction tbl_summary est extrêmement pratique pour présenter des tableaux esthétiques contenant de tris à plat :

tbl_summary(etab, include=type_d_etablissement_r)
Characteristic N = 2501
type_d_etablissement_r
    Ecole 150 (60%)
    Autre établissement 11 (4.4%)
    Grand établissement 24 (9.6%)
    Université 65 (26%)
1 n (%)

Ou même par groupe :

tbl_summary(etab, by=secteur_d_etablissement_r, include=c(region, type_d_etablissement_r))
Characteristic Privé
N = 86
1
Public
N = 164
1
region

    Auvergne-Rhône-Alpes 5 (5.8%) 16 (9.8%)
    Bourgogne-Franche-Comté 2 (2.3%) 4 (2.4%)
    Bretagne 5 (5.8%) 8 (4.9%)
    Centre-Val de Loire 0 (0%) 3 (1.8%)
    Collectivités d'outre-mer 0 (0%) 2 (1.2%)
    Corse 0 (0%) 1 (0.6%)
    Étranger 0 (0%) 4 (2.4%)
    Grand Est 5 (5.8%) 11 (6.7%)
    Guadeloupe 0 (0%) 1 (0.6%)
    Guyane 0 (0%) 1 (0.6%)
    Hauts-de-France 10 (12%) 8 (4.9%)
    Île-de-France 33 (38%) 53 (32%)
    La Réunion 0 (0%) 1 (0.6%)
    Mayotte 0 (0%) 1 (0.6%)
    Normandie 4 (4.7%) 9 (5.5%)
    Nouvelle-Aquitaine 5 (5.8%) 10 (6.1%)
    Occitanie 4 (4.7%) 20 (12%)
    Pays de la Loire 11 (13%) 4 (2.4%)
    Provence-Alpes-Côte d'Azur 2 (2.3%) 7 (4.3%)
type_d_etablissement_r

    Ecole 86 (100%) 64 (39%)
    Autre établissement 0 (0%) 11 (6.7%)
    Grand établissement 0 (0%) 24 (15%)
    Université 0 (0%) 65 (40%)
1 n (%)

Cette fonction peut être affinée afin d’afficher un titre, une légende, les p-value éventuelles, etc. Voici un article en anglais montrant ces différentes possibilités : https://www.danieldsjoberg.com/gtsummary/articles/tbl_summary.html

Prolongement : les tris à 3 variables

Comment réaliser des tris croisés avec plus de deux variables ? Il y a plusieurs méthodes, en voici une :

round(
  prop.table(ftable(etab$region, etab$type_etab, etab$secteur_d_etablissement), 1)
  *100, 1)

# Ici, les fonctions sont espacées afin de permettre une meilleure lecture.
# ftable permet de mettre plus de deux variables, là où la fonction table ne peut pas. La fonction ftable permet surtout de pouvoir mettre en forme les tris à trois variables. 
# prop.table permet de renvoyer les proportions (sur 1). Nous ajoutons ensuite l'argument 1 ; 1 veut dire qu'on souhaite avoir les pourcentages en ligne, 2 les pourcentages en colonne.
# On multiplie par 100 pour avoir les pourcentages (*100).
# Le dernier argument est pour la fonction round : nous voulons une décimale, nous donnons donc l'argument 1.

Pour plus d’informations sur des tris croisés à trois variables, voir : https://rstudio-pubs-static.s3.amazonaws.com/308591_6dff566d383946c881cb5b6a735a79fd.html.

5. Mise en forme avancée des données

5.1 Recodages conditionnels

Rappel : Les opérateurs

  • <- : marque l’assignation, création d’élément, stocker dans un objet
  • == : Egalité (A == B signifie “A est égal à B”)
  • != : Exclusion ( A != B signifie “A est différent de B”)
  • < : inférieur ||| <= : inférieur ou égal ||| > : supérieur ||| >= : supérieur ou égal
  • %in% : appartient à

Lorsque l’on souhaite enchaîner plusieurs conditions, on utilise :

  • Pour le OU : |
  • Pour le ET : &

Pour l’instant, nous avons surtout vu comment recoder les modalités d’une variable avec fct_collapse. Il est également possible de créer une variable en utilisant des conditions. Pour créer une variable, il suffit de lui assigner l’opération de recodage en combinant, grâce aux opérateurs, les conditions qui doivent être remplies.

Le code qui suit crée une variable catégorielle traitant de l’ancienneté des établissements de notre BDD. Sa syntaxe est celle de R-base, elle ne demande donc le chargement d’aucun package spécifique. D’autres méthodes peuvent par contre être plus courtes (voir les onglets correspondants).

etab$date_creation_cat<-NULL #cette ligne assigne des NA, il efface le contenu de cette variable. C'est une bonne pratique au cas où on se trompe et recode plusieurs fois la même variable.
etab$date_creation_cat[etab$date_creation >= 2000]<- "2000 ou après" #attention à l'ordre des commandes
etab$date_creation_cat[etab$date_creation < 2000]<- "1970-1999"
etab$date_creation_cat[etab$date_creation < 1970]<- "1945-1969"
etab$date_creation_cat[etab$date_creation < 1945]<- "1900-1944"
etab$date_creation_cat[etab$date_creation < 1900]<- "Avant 1900"
freq(etab$date_creation_cat)

Mise en pratique : Créons une nouvelle variable combinant le type de l’établissement et sa date de création (en 1945 ou avant / après 1945). Cette variable sera appelée type_anciennete.

etab$type_anciennete<-NULL #cette ligne assigne des NA, il efface le contenu de cette variable. C'est une bonne pratique au cas où on se trompe et recode plusieurs fois la même variable.
etab$type_anciennete[etab$type_d_etablissement_r=="Université" & etab$date_creation > 1945]<- "Université créée après 1945"
etab$type_anciennete[etab$type_d_etablissement_r=="Université" & etab$date_creation <= 1945]<- "Université créée en 1945 ou avant"
etab$type_anciennete[etab$type_d_etablissement_r=="Ecole" & etab$date_creation > 1945]<- "Ecole créée après 1945"
etab$type_anciennete[etab$type_d_etablissement_r=="Ecole" & etab$date_creation <= 1945]<- "Ecole créée en 1945 ou avant"
etab$type_anciennete[etab$type_d_etablissement_r=="Grand établissement" & etab$date_creation > 1945]<- "Grand établissement créé après 1945"
etab$type_anciennete[etab$type_d_etablissement_r=="Grand établissement" & etab$date_creation <= 1945]<- "Grand établissement créé en 1945 ou avant"
etab$type_anciennete[etab$type_d_etablissement_r=="Autre établissement" & etab$date_creation > 1945]<- "Autre établissement créé après 1945"
etab$type_anciennete[etab$type_d_etablissement_r=="Autre établissement" & etab$date_creation <= 1945]<- "Autre établissement créé en 1945 ou avant"
freq(etab$type_anciennete)

Beaucoup d’autres commandes de ce type existent, parmi elles se trouvent la fonction ifelse. Elle se décline comme suit :

  • ifelse(condition, si condition remplie, si condition non remplie)

Essayons en créant une variable sur la possession ou non d’un compte Linkedin par l’établissement :

etab$linkedin<-ifelse(!is.na(etab$compte_linkedin), "Oui", "Non") #!is.na(nom_base$nom_variable) veut dire "qui n'est pas une valeur manquante".

Mise en pratique : Utilisons le ifelse pour créer une nouvelle variable affichant “Oui” lorsque l’établissement est une université d’au moins 10000 étudiants pendant l’année universitaire 2017-2018, “Non” dans le cas contraire. Cette variable sera appelée universite_eff.

etab$universite_eff<-ifelse(etab$type_d_etablissement_r=="Université" & etab$effectifs_d_etudiants_inscrits_2017_18>=10000, "Oui", "Non")
#Nous réalisons un freq pour voir ce qu'il en est : 
freq(etab$universite_eff)

Prolongement : La fonction case_when

Une autre fonction pouvant permettre le recodage conditionnel est celle de case_when (package tidyverse/dplyr). Exemple pour la date de création de l’établissement en variable catégorielle, au lieu d’écrire comme tout à l’heure ceci :

etab$date_creation_cat<-NULL #cette ligne assigne des NA, il efface le contenu de cette variable. C'est une bonne pratique au cas où on se trompe et recode plusieurs fois la même variable.
etab$date_creation_cat[etab$date_creation >= 2000]<- "2000 ou après" #attention à l'ordre des commandes
etab$date_creation_cat[etab$date_creation < 2000]<- "1970-1999"
etab$date_creation_cat[etab$date_creation < 1970]<- "1945-1969"
etab$date_creation_cat[etab$date_creation < 1945]<- "1900-1944"
etab$date_creation_cat[etab$date_creation < 1900]<- "Avant 1900"

On écrira ceci :

etab$date_creation_cat<-NULL
etab$date_creation_cat<-case_when(etab$date_creation < 1900~"Avant 1900", 
                                  etab$date_creation < 1945~"1900-1944", 
                                  etab$date_creation < 1970~"1945-1969", 
                                  etab$date_creation < 2000~"1970-1999", 
                                  etab$date_creation >= 2000~"2000 ou après",
                                  T~NA_character_) # Se retranscrit comme : "Tout ce qui reste, mets-le en NA, c'est une variable de type character".

6. Sélections, filtres et tris (tidyverse ou dplyr)

La commande select permet de sélectionner les variables nous intéressant :

type_sect<-select(etab, identifiant_interne, type_d_etablissement_r, secteur_d_etablissement_r)

La commande slice permet de sélectionner et afficher des lignes :

slice(etab, 1:5) #affiche les 5 premières lignes

Il est également possible d’effectuer des filtres :

univ<-filter(etab, type_d_etablissement_r=="Université" & region %in% c("Île-de-France", "Hauts-de-France"))

Ou de trier les données :

etab<-arrange(etab, desc(effectifs_d_etudiants_inscrits_2017_18))
#par défaut, croissant
#desc = décroissant

Prolongement : L’opérateur %>% (pipe)

Si l’on souhaite utiliser plusieurs fonctions afin d’arranger la sortie de nos données, il est possible de les encastrer :

slice(
  select(
    arrange(
      filter(
        etab, type_d_etablissement_r=="Université"),
      desc(effectifs_d_etudiants_inscrits_2017_18)),
    type_d_etablissement_r, effectifs_d_etudiants_inscrits_2017_18, date_creation),
  1:2)

… Ou de les écrire à la suite, mais cette méthode implique la création d’un objet intermédiaire, qui en réalité n’est pas nécessaire :

exo <- filter(etab, type_d_etablissement_r=="Université")
exo <- arrange(exo, desc(effectifs_d_etudiants_inscrits_2017_18))
exo <- select(exo, type_d_etablissement_r, effectifs_d_etudiants_inscrits_2017_18, date_creation)
exo <- slice(exo, 1:2)
exo

L’opérateur %>% (pipe, Ctrl + Shift + M) permet d’enchaîner les fonctions en prenant comme argument principal le résultat de la fonction précédente : f(a) s’écrit a %>% f() ; Ce qui est à gauche de %>% est basculé en premier argument de ce qui suit l’opérateur.

Ce qui donne : table %>% fonction1() %>% fonction2() au lieu de fonction2(fonction1(table)). Dans notre cas, par exemple, nous souhaitons afficher une sortie regroupant les 10 plus vieux établissements du secteur public, en affichant uniquement les variables concernant le secteur, la date de création, l’identifiant et le type de l’établissement.

etab %>% 
  filter(secteur_d_etablissement_r=="Public") %>% 
  arrange(date_creation) %>% 
  select(secteur_d_etablissement_r, date_creation, identifiant_interne, type_d_etablissement_r) %>% 
  slice(1:10)

7. Réalisation de graphiques simples

Quel graphique pour quelle problématique ?

Dans la recherche, les boîtes à moustache, nuages de points ou graphiques en courbes sont des graphiques assez couramment utilisés. Certains graphiques, comme les diagrammes circulaires, sont évités en sociologie. Dans le secteur privé, les graphiques (ou illustrations) utilisés sont (à mon sens) plus diversifiés.

R possède des fonctions de base pour réaliser des graphiques simples.

J’aimerais observer la répartition des effectifs de l’établissement en 2017-2018. Il est possible de faire un summary, mais pour l’observer visuellement on peut choisir de se diriger vers un boxplot. Le boxplot, ou encore boîte à moustaches, est un graphique permettant d’observer différents indices de répartition.

boxplot(etab$effectifs_d_etudiants_inscrits_2017_18)

Pour l’interprétation d’un boxplot (ou boîte à moustaches) :

7.1 Afficher plusieurs graphiques sur un même plan

Ci-dessous la fonction par() qui permet de délimiter une “zone” pour disposer les graphiques :

par(mfrow = c(nombre de lignes, nombre de colonnes))

Typiquement, on utilisera cette fonction avec les fonctions permettant de créer des graphiques simples (boxplot(), barplot(), etc.).

par(mfrow = c(2, 2))
plot(~ anciennete + effectifs_d_etudiants_inscrits_2017_18, etab, main = "Ancienneté de l'établissement et effectifs en 2017-2018", ylab="Effectifs en 2017-2018", xlab="Ancienneté")
hist(etab$effectifs_d_etudiants_inscrits_2017_18, col="cornflowerblue", main="Répartition des effectifs en 2017-2018", xlab="Effectifs en 2017-2018")
boxplot(etab$effectifs_d_etudiants_inscrits_2017_18, main = "Répartition des effectifs en 2017-2018", ylab="Effectifs en 2017-2018")
boxplot(effectifs_d_etudiants_inscrits_2017_18 ~ type_d_etablissement, etab, main = "Répartition des effectifs en 2017-2018 selon le type d'établissement", ylab = "Effectifs en 2017-2018", xlab = "Type d'établissement")

Vous remarquerez que par(mfrow = c(2, 2)) continue d’agir lorsqu’on tente de réaliser un boxplot() par exemple. Pour reset les paramètres graphiques :

par(mfrow = c(1, 1))

8. Réalisation de graphiques avec ggplot2

8.1 Syntaxe de ggplot2

Le package ggplot2 est dédié aux graphiques. Sa syntaxe ressemble à celle du tidyverse. L’intérêt de ggplot2 est de produire des graphiques complexes par ajout de couches successives. La syntaxe de base de ggplot est :

ggplot(data) + geom_X (aes(x = Variable_abscisses, y = Variable_ordonnées))

ggplot() définit la source des données, geom_X() le type de graphique que l’on souhaite, aes() les données à représenter.

Selon les préférences, les lignes de codes peuvent être ré-arrangées légèrement, comme nous pouvons le voir ci-dessous :

library(ggplot2)
ggplot(etab) + #La base de données
  geom_bar(aes(x=type_d_etablissement_r), stat="count") #Représentation d'un diagramme en barres (geom_bar)

ggplot(etab) + #La base de données
  aes(x=type_d_etablissement_r) + #La variable type_eec en x et calcul des effectifs pour chaque catégorie
  geom_bar(stat="count") #Un diagramme en barres, l'option "count" veut dire qu'on souhaite représenter les effectifs

Ce graphique ci-dessous comptabilise uniquement les effectifs des différents types d’établissement pour notre base.

8.1.1 Les données à représenter : aes

Les options de aes (pour aesthetics) permettent d’associer une donnée à un type de représentation. Les principaux sont :

x = axe des abscisses

y = axe des ordonnées

size = taille des points

col = couleur des points/contours

alpha = transparence

fill = couleur des aplats

Par exemple, on souhaite obtenir le même graphique que précédemment, mais avec des couleurs différentes, il faudra faire en sorte d’avoir une variable de type factor :

ggplot(etab)+
  aes(x=type_d_etablissement_r, 
      fill=type_d_etablissement_r) +
  geom_bar(stat="count")

8.1.2 Les types de graphiques : geom_X

Les geom_X correspondent aux types de graphiques souhaités. Les principaux sont :

  • geom_bar : Diagramme en barres
  • geom_histogram : Histogramme
  • geom_point : Nuage de points
  • geom_boxplot : Boxplot
  • geom_line : Lignes
  • geom_text : Ajout de texte
  • geom_label : Labels

En fonction de la représentation, différentes options existent.

8.1.3 Les intitulés : labs

L’argument labs permet d’afficher un titre pour le graphique ainsi que les intitulés des axes x et y.

ggplot(etab)+
  aes(x=type_d_etablissement, 
      fill=type_d_etablissement) +
  geom_bar(stat="count") +
  labs(title="Nombre d'établissements du supérieur", x="Type d'établissement", y="Effectifs", fill="Type d'établissement", caption="Données des principaux établissements de l'enseignement supérieur")

Ici on préférera enlever la légende, comme ceci :

ggplot(etab)+
  aes(x=type_d_etablissement, 
      fill=type_d_etablissement) +
  geom_bar(stat="count") +
  labs(title="Nombre d'établissements du supérieur", x="Type d'établissement", y="Effectifs", caption="Données des principaux établissements de l'enseignement supérieur") +
  theme(legend.position = "none")

Bien sûr, pour qu’un graphique puisse être recevable, il est aussi nécessaire d’inclure des intitulés clairs de modalités.

8.2 L’histogramme : geom_histogram

ggplot(etab) +
  aes(x = effectifs_d_etudiants_inscrits_2017_18) +
  geom_histogram(bins = 30)

Plus on a de barres, plus on a une vision claire de la distribution des effectifs. On peut également superposer sur ces histogrammes une courbe de densité :

ggplot(etab) +
  aes(x = effectifs_d_etudiants_inscrits_2017_18) +
  geom_histogram(aes(y=..density..), bins = 30) +
  geom_density()

8.3 Le diagramme en barres : geom_bar

Hormis certains cas spécifiques, afficher sous forme de graphique une seule variable n’est souvent pas nécessaire.

Ci-dessous un graphique permettant de visualiser rapidement la réparition des dates de création (en tranches) en fonction du type d’établissement :

ggplot(etab)+
  aes(x = type_d_etablissement_r, fill = date_creation_cat) +
  geom_bar(position="fill") + #la position des barres peut être changée avec "dodge", "fill" = catégories empilées à 100 %
  labs(title="Création des établissements du supérieur", x="Type d'établissement", y="Proportion", fill="Période de création")

# pour obtenir les % pour l'axe y : scale_y_continuous(labels = scales::percent)
ggplot(etab)+
  aes(x = type_d_etablissement_r, fill = date_creation_cat) +
  geom_bar(position="fill") + #la position des barres peut être changée avec "dodge", "fill" = catégories empilées à 100 %
  labs(title="Création des établissements du supérieur", x="Type d'établissement", y="Proportion", fill="Période de création") +
  scale_y_continuous(labels = scales::percent) +
  viridis::scale_fill_viridis(discrete=T) #viridis est un package permettant d'obtenir des palettes de couleur visibles pour les personnes daltoniennes.

ggplot(etab)+
  aes(x = type_d_etablissement_r, fill = date_creation_cat) +
  geom_bar(position="fill") + #la position des barres peut être changée avec "dodge", "fill" = catégories empilées à 100 %
  labs(title="Création des établissements du supérieur", x="Type d'établissement", y="Proportion", fill="Période de création") +
  theme(axis.text.x = element_text(angle=45, hjust=1), axis.text.y = element_text(angle=45, hjust=1)) + #pour afficher les intitulés en biais sur l'axe x et y
  scale_y_continuous(labels = scales::percent) +
  scale_fill_brewer(palette="Blues")

8.4 Le boxplot : geom_boxplot

ggplot(etab) +
  aes(y = effectifs_d_etudiants_inscrits_2017_18)+
  geom_boxplot()

ggplot(etab) +
  aes(x=type_d_etablissement_r, y = effectifs_d_etudiants_inscrits_2017_18)+
  geom_boxplot()

Vous remarquerez qu’il n’y a pas la moyenne sur notre boxplot. Pour y remédier, il faudra utiliser la fonction stat_summary :

ggplot(etab, aes(x=type_d_etablissement_r, y = effectifs_d_etudiants_inscrits_2017_18)) +
    geom_boxplot() +
    stat_summary(fun=mean)

…et il est tout à fait possible de personnaliser le boxplot :

ggplot(etab, aes(x=type_d_etablissement_r, y = effectifs_d_etudiants_inscrits_2017_18)) +
    geom_boxplot(colour="cornflowerblue") +
    stat_summary(fun=mean, geom="point", color="cornflowerblue", fill="cornflowerblue")

ggplot(etab, aes(x=type_d_etablissement_r, y = effectifs_d_etudiants_inscrits_2017_18, fill=type_d_etablissement_r)) +
  geom_boxplot() +
  stat_summary(fun=mean, geom="point")

ggplot(etab) +
  geom_boxplot() +
  aes(x=type_d_etablissement_r, y = effectifs_d_etudiants_inscrits_2017_18, fill=type_d_etablissement_r) +
  labs(title = "Nombre total d'heures travaillées la semaine de référence selon le sexe", x ="Sexe", y = "Nombre total d'heures travaillées") +
  stat_summary(fun=mean, geom="point", size=1.5, color="red", fill="red") +
  theme_minimal()

Beaucoup d’options existent, n’hésitez pas à les explorer.

8.5 Le nuage de points

etab$effectifs_d_etudiants_inscrits_2010_11 <- gsub(" ","", etab$effectifs_d_etudiants_inscrits_2010_11)
etab$effectifs_d_etudiants_inscrits_2010_11 <- as.numeric(etab$effectifs_d_etudiants_inscrits_2010_11)

ggplot(etab)+
  geom_point(aes(x = effectifs_d_etudiants_inscrits_2010_11, y = effectifs_d_etudiants_inscrits_2017_18, colour=type_d_etablissement_r)) +
  labs(title="Effectifs d'étudiant·es et création des établissements du supérieur", x="Effectifs d'étudiant·es en 2017-2018", y="Effectifs d'étudiant·es en 2010-2011", colour="Type d'établissement")

ggplot(etab)+
  geom_point(aes(x = effectifs_d_etudiants_inscrits_2010_11, y = effectifs_d_etudiants_inscrits_2017_18, colour=type_d_etablissement_r)) +
  labs(title="Effectifs d'étudiant·es et création des établissements du supérieur", x="Effectifs d'étudiant·es en 2017-2018", y="Effectifs d'étudiant·es en 2010-2011", colour="Type d'établissement") +
  scale_colour_brewer(palette="Set3") # cf. les palettes du packages RColorBrewer

8.6 Le package GGally

Le package GGally possède des fonctionnalités pouvant résumer la répartition de certaines variables. Ici, un exemple avec l’enquête Emploi en continu (EEC) de 2022 (version libre d’accès).

library(GGally)

eec$SEXE<-factor(eec$SEXE)
levels(eec$SEXE) <- c("Hommes", "Femmes")

eec$TPPRED<-factor(eec$TPPRED)
levels(eec$TPPRED) <- c("Temps complet", "Temps partiel")

eec$PCS1_R<-eec$PCS1
eec$PCS1_R[eec$PCS1==0]<-NA
freq(eec$PCS1_R)
eec$PCS1_R<-factor(eec$PCS1_R)

ggbivariate(data = eec, outcome = "TPPRED", explanatory = c("SEXE", "PCS1_R"))

ggtable(data = eec, columnsX = "TPPRED", columnsY = c("SEXE", "PCS1_R"))

Avec des % en ligne :

ggtable(data = eec, columnsX = "TPPRED", columnsY = c("SEXE", "PCS1_R"), cells="row.prop")

8.7 Le package esquisse

Le package esquisse permet d’ajouter une extension “clique-boutons” au sein de R. Elle est très pratique pour les personnes ayant des difficultés à comprendre la syntaxe de ggplot2.

library(esquisse) #je charge le package

Esquisse peut être lancé via l’onglet Addins (ggplot2 builder) ou via la console, en tapant : esquisse:::esquisser().

9. Transformations de tables

9.1 Jointure de tables

Il est possible de regrouper des bases liées entre elles. On peut les regrouper si on dispose d’une clé d’appariemment (ou clé de jointure, une variable commune à deux tables). La fonction merge nécessite l’ajout de certains arguments, notamment la clé de jointure qui peut prendre la forme d’un identifiant unique, ou encore l’indication de garder (ou non) l’ensemble des variables des deux bases.

# il est possible d'utiliser la fonction merge, mais ici on préférera les alternatives du package dyplyr (chargé avec le tidyverse) :

nom_base_jointure<-left_join(x, y, by = "identifiant_interne")
# x = première base
# y = deuxième base
# Dans le cas d'un identifiant qui ne porte pas le même nom dans les deux bases, on peut 1) soit renommer l'identifiant d'une des deux bases, 2) soit inclure d'autres options dans la fonction merge, comme ceci : 
nom_base_jointure<-left_join(x, y, by=c("nom_identifiant"="nom_identifiant_different"))

D’autres possibilités existent avec le package dplyr, voir cette cheatsheet sur les packages dplyr et tidyr, et sa partie sur les jointures : https://www.rstudio.com/wp-content/uploads/2015/02/data-wrangling-cheatsheet.pdf.

Regroupements de lignes

Il peut être utile de regrouper plusieurs observations selon un ou plusieurs critères afin de produire des calculs (moyenne des effectifs selon le type d’établissement par exemple). La fonction group_by permet de produire ces regroupements et est associée à une fonction de calcul dans summarise. Par exemple :

Exemple 1 : Calculer la moyenne d’étudiants inscrits en 2017-2018 selon le type d’établissement

etab %>% 
  group_by(type_d_etablissement_r) %>% 
  summarise(Moyenne=mean(effectifs_d_etudiants_inscrits_2017_18, na.rm = T))

Exemple 2 : Calculer pour l’Île-de-France le nombre moyen d’étudiants inscrits en 2017-2018 selon le secteur

etab %>%
  filter(region=="Île-de-France") %>% 
  group_by(secteur_d_etablissement_r) %>% 
  summarise(Moyenne=round(mean(effectifs_d_etudiants_inscrits_2017_18, na.rm = T), 1)) %>%
  rename("Secteur de l'établissement" = "secteur_d_etablissement_r") %>% #le rename ne change pas durablement le nom de la variable dans la table, ici le nom n'est changé que pour l'affichage dans la console.
  arrange(desc(Moyenne))

Ressources

Introduction aux méthodes quantitatives

  • Barnier J., 2008, « Tout ce que vous n’avez jamais voulu savoir sur le χ2 sans jamais avoir eu envie de le demander ».
  • Chanvril-Ligneel F., Le Hay V., 2014, Méthodes statistiques pour les sciences sociales, Ellipses.
  • Gros J., 2017, « Quantifier en ethnographe », Genèses, 108, 3, p. 129‑147.
  • Guay J.-H., 2014, Statistiques en sciences humaines avec R, De Boeck Supérieur.

Tutoriels R (en général) et aides disponibles

  • Le site de Joseph Larmarange : https://larmarange.github.io/analyse-R/.
  • Le site edX ont parfois des formations gratuites, mais ils ne sont pas nécessairement donnés par des chercheur·ses en SHS, les pratiques peuvent donc ne pas être les mêmes.
  • Divers forums, notamment la communauté de Stackoverflow pour tout ce qui relève de l’interprétation des messages d’erreur.

Tests statistiques

  • Le site DellaData a beaucoup d’articles sur les tests statistiques : https://delladata.fr/
  • Pour le Khi-2 (chisq.test), le test de Shapiro (shapiro.test), etc. (les tests les plus connus), le package stats, intégré à l’installation de R.
  • Le V de Cramer (cramer.v) est dans le package questionr.
  • Les packages rstatix (test de kruskal-wallis), ggpubr pour les diagrammes de densité, QQ-plot.

Données pondérées

  • Le package survey (attention à bien lire la documentation, l’onglet “aide”, pour certaines fonctions).

Régressions

  • En fonction du type de régression voulue, par exemple ordinal.
  • Pour les régressions avec des données pondérées, prendre le package survey (les fonctions R plus classiques ont des options pour prendre en compte les pondérations, mais pas forcément de la manière dont on le souhaite), exemple : https://stats.stackexchange.com/questions/57107/use-of-weights-in-svyglm-vs-glm
  • Le package rcompanion pour les indicateurs de qualité des régressions.

Divers : applications, analyse textuelle, webscraping, cartographie.

  • Applications : le package shiny.
  • Analyse textuelle : les packages stringr (pour manipuler les chaînes de caractères) et tidytext.
  • Webscraping : les packages httr et rvest.
  • Cartographie : les packages sf, geojsonio et ggspatial.